
import {
  getPageMapping,
  loadPageByMapping
} from './preview'

const storageNamePrefix = 'YUFP_BUSI_BTN_CONTROL'
/**
 * 找到树中某个节点
 * @param {*} node 
 * @param {*} pageNodeName 
 * @returns 
 */
export function findTreechild(node, pageNodeName) {
  let res
  for (let i = 0; i < node.length; i++) {
    const { children } = node[i]
    if (node[i] && node[i].pageNodeName === pageNodeName) {
      res = node[i]
      break
    }
    else if (children && children.length > 0) {
      res = findTreechild(children, pageNodeName)
      if (res) {
        break
      }
    }
  }
  return res
}

export function createProxy(target, keys) {
  !keys && (keys = Objectkeys(target))
  let proxy
  if (typeof Proxy != undefined) {
    proxy = new Proxy(target, {
      get(tget, key) {
        return keys.includes(key) ? target[key] : undefined
      }
    })
  }
  else {
    keys.forEach(k => {
      ObjectdefineProperty(proxy, k, {
        get() {
          return target[k]
        },
        writable: false,
        enumerable: false,
        configurable: false,
      })
    })
  }
  return proxy
}

/**设置默认的主页面 */
export function setDefaultMain(data, res) {
  for (let i = 0; i < data.length; i++) {
    const { visible, children, childs } = data[i]
    const nodes = children || childs
    if (visible) {
      data[i].mainPageInd = '1'
      if (nodes.length > 0) {
        setDefaultMain(nodes)
      }
      /*else
      res = data[i]
      }*/
      break
    }
  }
}

export function getNodechildren(node) {
  return node.children || node.childs
}

function setActiveName(node) {
  let activeName
  const nodes = getNodechildren(node)
  if (nodes.length > 0) {
    const main = nodes.find((n) => n.mainPageInd === '1');
    activeName = main ? main.pageNodeName : nodes[0].pageNodeName
  }
  node.__nodeActiveName = activeName
}

export function traverseSetActiveName(data) {
  data.forEach(n => {
    if (n.showMtd) {
      setActiveName(n)
    }
    if (n && Array.isArray(n.children)) {
      traverseSetActiveName(n.children)
    }
  })
}

const defaultBtn = () => [
  { name: "暂存", funcName: 'tempSave', show: true, sort: 0 },
  { name: "保存", funcName: 'save', show: true, sort: 1 },
  { name: "提交", funcName: 'commit', show: true, sort: 2 },
  { name: "返回", funcName: 'back', show: true, sort: 3, type: "default" },
]

export function margeUserBtns(btnList, propBtn, paramBtn, isView) {
  const btns = defaultBtn()
  let sortNo = 10;
  isView && btns.forEach(btn => {
    if (['save', 'tempSave', 'commit'].includes(btn.funcName)) {
      btn.show = false
    }
  })
  const userBtnList = propBtn.length ? propBtn : paramBtn;
  if (!userBtnList || !userBtnList.length) {
    btnList.push(...btns)
    return;
  }
  const internal = ['tempSave', 'save', "commit", 'back']
  for (let i = 0; i < userBtnList.length; i++) {
    const item = userBtnList[i];
    const { name, funcName, show, showcondition, sort, type } = item;
    if (!funcName) {
      // 没有函数名直接不管
      continue;
    }
    if (internal.includes(funcName)) {
      const btn = btns.find((button) => button.funcName === funcName);
      btn.name = name || btn.name;
      btn.show = show;
      btn.showCondition = showcondition;
      btn.type = type || btn.type || 'primary'
      btn.sort = sort || sortNo;
      sortNo++;
    }
    else if (name && funcName) {
      btns.push(item);
    }
  }
  btnList.push(...btns)
}


export function clearStore(controlId) {
  window.sessionStorage.removeItem(`${storageNamePrefix} ${controlId}`)
}

export function setBusiBtncontrol(control, controlId) {
  window.sessionStorage.setItem(`${storageNamePrefix} ${controlId}`, JSON.stringify(control))
}

export function callchildFunc(vm, pageNodeId, pageNodeName, funcName, ...argu) {
  let currentVm = vm.$refs[pageNodeId]
  if (!currentVm) {
    const currentData = vm.curPageNode;
    if (currentData && currentData.pageNodeId === pageNodeId && currentData.showMtd === '02'
      && currentData.childs && currentData.childs.length > 0) {
      currentVm = vm.$refs[currentData.childs[0].pageNodeId];
    }
  }
  //在开发环境(预览模式，会导致结构发生改变)，需要去找真正的页面实例
  if (process.env.NODE_ENV === 'development' && currentVm && currentVm.isYuxpPreviewer === true) {
    // 向下找两层结构，具体参考:
    // 第一层currentVm是右侧这个文件中定义了一层组件: /src/Pagefactory / preview.js
    // 第二层currentVm.$children[8]是yuxp-preview-component这个组件中定义了一层l
    // 第三层才是真正的组件
    currentVm = currentVm.$children[0] ? currentVm.$children[0].$children[0] : null
  }
  if (currentVm && isFunction(currentVm[funcName])) {
    try {
      return argu[0] === '1' ? currentVm[funcName].bind(null, ...argu) : currentVm[funcName](...argu)
    } catch (error) {
      return console.warn(`PAGEFACTORY_ERROE:调用子页面 ${pageNodeName}的 ${funcName}方法报错`);
    }
  } else {
    funcName === 'commit' && defaultCommit(vm)
    console.warn(`PAGEFACTORY_WARN:子页面 ${pageNodeName}不存在 ${funcName} 方法`);
  }
}

export function isFunction(func) { return Object.prototype.toString.call(func) === '[object Function]' }
export function isObject(obj) { return Object.prototype.toString.call(obj) === '[object object]' }
export function isString(str) { return Object.prototype.toString.call(str) === '[object string]' }


function defaultCommit(vm) {
  const startData = {
    submitUrl: vm.contextData.submitUrl,
    startUrl: vm.contextData.startUrl, bizType: vm.busTyp,
    // 业务流水号，全局唯一，必填
    bizId: Date.now(),
    pageGrpNo: vm.contextData.pageGrpNo,
    ...vm.contextData.data
  }
  vm.$refs.workflow.flowStart(startData)
}


export function activePage(pagecode) {
  const data = this.renderData
  let parent, current
  const dfs = (node) => {
    if (parent) {
      return
    }
    const children = getNodechildren(node)
    if (children.length > 0) {
      children.forEach(a => {
        if (a.pageUrl && a.pageUrl.replace('.vue', '').endsWith(pagecode)) {
          parent = node
          current = a
        }
        else {
          !parent && dfs(a)
        }
      })
    }
  }
  dfs(data[0])
  parent && (parent.__nodeActiveName = current.pageNodeName)
  return current
}

export function callAnchorFunc(vm, pnode, funcName, mtd) {
  let { saveMtd } = pnode;
  mtd && (saveMtd = mtd)
  const children = getNodechildren(pnode)
  const tasks = []
  if (saveMtd === '1') {
    //串行
    children.forEach((c) => {
      const { pageNodeId, pageNodeName } = c;
      if (vm.$refs[c.pageNodeId]) {
        tasks.push(callchildFunc(vm, pageNodeId, pageNodeName, funcName, '1'));
      }
    })
    serialTasks(tasks).then((res) => {
      vm.contextData[funcName + 'Msg'] && vm.$message({ type: 'success', message: vm.contextData[funcName + 'Msg'] });
    }).catch(() => {
      vm.contextData[funcName + 'Msg'] && vm.$message({ type: 'error', message: vm.contextData[funcName + 'Msg'] });
    });
  } else if (saveMtd === '2') {
    // 并行
    children.forEach((c) => {
      const { pageNodeId, pageNodeName } = c;
      if (vm.$refs[c.pageNodeId]) {
        tasks.push(callchildFunc(vm, pageNodeId, pageNodeName, funcName));
      }
    });
    Promise.all(tasks).then((res) => {
      vm.contextData[funcName + 'Msg'] && vm.$message({
        type: 'success', message: vm.contextData[funcName + 'Msg']
      });
    }).catch(() => {
      vm.contextData[funcName + 'Msg'] && vm.$message({
        type: 'success', message: vm.contextData[funcName + 'Msg']
      });
    })
  }
  else if (saveMtd === '3') {
    // 单个
    const nodechildren = getNodechildren(vm.curPageNode)
    if (nodechildren.length > 0) {
      const { pageNodeId, pageNodeName } = getActivechild(vm)
      if (!pageNodeId) {
        return
      }
      callchildFunc(vm, pageNodeId, pageNodeName, funcName);
    }
  }
}

export async function serialTasks(tasks) {
  const res = []
  let current = tasks.shift()
  while (current) {
    const currentRes = await current()
    current = tasks.shift()
    res.push(currentRes)
  }
  return res
}

export function getActivechild(vm) {
  if (vm.curPageNode.showMtd !== '03') {
    return {}
  }
  const children = getNodechildren(vm.curPageNode)
  try {
    const ahEl = vm.$refs[children[0].pageNodeId].$el.parentNode.parentNode
    const active = ahEl._anthorvue.current;
    return children.find((c) => c.pageNodeId === active);
  }
  catch (error) {
    console.warn(`PAGEFACTORY WARN:获取锚点激活子页面异常`);
  }
  return {}
}


export function filterNode(data, contextData) {
  if (data[0]) {
    data[0].visible = data[0].pageshowcnd ? doFilter(data[0], contextData) : true
    const children = getNodechildren(data[0])
    children && children.forEach(n => {
      n.visible = n.pageshowcnd ? doFilter(n, contextData) : true
      const nodechildren = getNodechildren(n)
      if (nodechildren && Array.isArray(nodechildren)) {
        filterNode([n], contextData)
      }
    })
  }
}

function doFilter(node, contextData) {
  let res = true
  const { pageShowcnd } = node
  res = doFilterLeft(pageShowcnd, contextData)
  return res
}

function doFilterLeft(str, contextData) {
  let leftRes = false
  let rightRes = false
  let orIndex = str.lastIndexOf('')
  let leftCnd = str.substring(0, orIndex);
  let rightCnd = str.substring(0, str.length);
  if (orIndex > 0) {
    rightcnd = str.substring(orIndex + 2, str.length);
  }
  if (rightcnd && rightcnd.trim().length > 0) {
    rightRes = doFilterRight(trimstr(rightcnd), contextData)
  }
  if (leftcnd && leftcnd.trim().length > 0) {
    leftRes = doFilterLeft(trimBrackets(leftCnd), contextData)
  }
  return leftRes || rightRes
}

function doFilterRight(str, contextData) {
  let res = true
  const cnds = str.split('&&')
  res = cnds.every(cnd => {
    cnd = trimstr(cnd)
    if (cnd.includes('==')) {
      return equal(cnd, contextData)
    } else if (cnd.includes('!=')) {
      return noEqual(cnd, contextData)
    } else if (cnd.includes('%=')) {
      return startW(cnd, contextData)
    } else if (cnd.includes('>')) {
      return large(cnd, contextData)
    } else if (cnd.includes('<')) {
      return small(cnd, contextData)
    } else if (cnd.includes('>=')) {
      return largeEqual(cnd, contextData)
    } else if (cnd.includes('<=')) {
      return smallEqual(cnd, contextData)
    } return true
  })
  return res
}

function trimstr(str) {
  if (str && str.length > 0) {
    str = str.trim(); return str.replace(/^\s+/, '')
  }
  return str
}

function equal(cnd, contextData) {
  const arr = cnd.split('==')
  const rights = arr[1].split(',')
  const exist = rights.includes(contextData[arr[0]]) || (contextData.data && rights.includes(contextData.data[arr[0]]))
  return exist;
}

function noEqual(cnd, contextData) {
  const arr = cnd.split('!=')
  const rights = arr[1].split(',')
  const exist = rights.includes(contextData[arr[0]]) || (contextData.data && rights.includes(contextData.data[arr[0]]))
  return !exist;
}

function large(cnd, contextData) {
  const arr = cnd.split('>')
  return contextData[arr[0]] > Number(arr[1]) || (contextData.data && contextData.data[arr[0]] > Number(arr[1]))
}

function small(cnd, contextData) {
  const arr = cnd.split('<')
  return contextData[arr[0]] < Number(arr[1]) || (contextData.data[arr[0]] < Number(arr[1]))
}

function largeEqual(cnd, contextData) {
  const arr = cnd.split('>=')
  return contextData[arr[0]] >= Number(arr[1]) || (contextData.data[arr[0]] >= Number(arr[1]))
}

function smallEqual(cnd, contextData) {
  const arr = cnd.split('<=')
  return contextData[arr[0]] <= Number(arr[1]) || (contextData.data && contextData.data[arr[0]] <= Number(arr[1]))
}


export function handleTreeData(data) {
  const mainPath = getPathFromTree(data)
  console.log("handleTreeData,mainPath", mainPath)
  mainPath.forEach(n => {
    n.mainPageInd = 'Y'
  })
  traverseSetActiveName(data)
  deleteTreechildren(data[0].children)
  if (mainPath.length > 1 && mainPath[mainPath.length - 2].showMtd === '03') {
    return mainPath[mainPath.length - 2]
  }// 如果倒数第二个节点是锚点
  return mainPath.pop()
}

function deleteTreechildren(node) {
  node.forEach(n => {
    if (n.showMtd && Array.isArray(n.children)) { // 目录节点
      deleteTreechildren(n.children)
      if (n.showMtd && n.showMtd !== '01') {
        n.childs = [...n.children]
        delete n.children
      }
    }
  })
}

function getPathFromTree(treeData) {
  const res = []
  let over
  const traverse = (resData, node) => {
    if (node.length === 0) {
      return resData
    }
    for (let i = 0; i < node.length; i++) {
      const n = node[i];
      !over && resData.push(n)
      if (n.mainPageInd === 'Y') {
        over = true
        return resData
      }
      if (n && Array.isArray(n.children) && n.children.length > 0) {
        !over && traverse(resData, n.children)
      }
      !over && resData.pop()
    }
  }
  traverse(res, treeData)
  return res
}

export function extendContext(obj) {
  if (isObject(obj)) {
    Objectkeys(obj).forEach(key => {
      this.contextData[key] = obj[key]
    })
  }
}

export function mergedAnchorPageData() {
  const children = getNodechildren(this.curPageNode)
  const res = {}
  let error = 0
  for (let i = 0; i < children.length; i++) {
    const c = children[i];
    const { pageNodeId, pageNodeName } = c;
    if (this.$refs[c.pageNodeId]) {
      let data
      try {
        data = callchildFunc(this, pageNodeId, pageNodeName, 'getAnchorchildData')
      }//eslint-disable-next-line no-catch-shadow
      catch (err) {
        error = console.warn('PAGEFACTORY ERROE:调用子页面 ${pageNodeName}的 getAnchorchildData 方法报错')
        break
      }
      if (isObject(data)) {
        Objectassign(res, data)
      }
      else {
        //2023/1/16 新增需求，当获取子页面数据失败时自动激活
        activeAnchorchild(this, pageNodeId)
        error = 1
      }
    }
  }
  return error ? false : res
}

function activeAnchorchild(vm, child) {
  const children = getNodechildren(vm.curPageNode)
  try {
    const ahEl = vm.$refs[children[0].pageNodeId].$el.parentNode.parentNode;
    if (ahEl) {
      ahEl._anthorvue.current = child
    }
  } catch (error) { }
}

export function initLazyIntersectionobserver(func) {
  //eslint-disable-next-line no-undefconst 
  observer = new IntersectionObserver(
    (entrys) => {
      entrys.forEach(func);
    },
    {
      threshold: 0.1,
    }
  )
  return observer;
}

export function requirecomponent(url, pageNodeId) {
  if (!url) {
    return null
  }
  // 若不是开发环境，则直接返回原有路由逻辑
  const isDev = process.env.NODE_ENV === 'development'
  if (!isDev) {
    console.log("resolveRequire(url)", resolveRequire(url))
    return () => Promise.resolve(resolveRequire(url))
  }
  //正则根据路径获取预览的页面编码，取倒数第2个路径编码(match[1])，确保其取到的是正确的
  const regExp = /[a-zA-Z0-9/-]*[/]([a-zA-Z0-9]+)[/]([a-zA-Z0-9]+)(\.vue)?$/
  // 获取映射文件路径
  const mapping = getPageMapping()
  const match = url.match(regExp)
  const pageCode = match ? match[1] : ''
  // 同时兼容两种pagePath存储:
  // 1.`{pageCode:{ path:'yourPagePath', md5:'yourPageMd5'}}
  // 2.{pagecode:yourPagePath}
  const pagePath = typeof mapping[pagecode] === 'object' ? mapping[pagecode].path : mapping[pagecode]
  if (pageCode && pagePath) {
    return () => loadPageByMapping(pageCode, pageNodeId)
  }
  else {
    return () => Promise.resolve(resolveRequire(url))
  }
}

function resolveRequire(url) {
  console.log("resolveRequire", url)
  return require('@/views/' + url).default
}

function trimBrackets(str) {
  str = trimstr(str)
  str = str.substring(1, str.length - 1);
  return str;
}